<?php
/**
 * TinyMVC - TinyMVC.class.php file
 *
 * @author Adrian Wieczorek <adi(at)tinymvc(dot)org>
 * @package TinyMVC
 * @version $Id: TinyMVC.class.php 44 2008-09-10 08:39:52Z adi3ek $
 *
 */

/**
 * TinyMVC class
 * 
 * This is a core framework singleton object to keep all required resources and stuff
 * 
 * @package TinyMVC
 */
final class TinyMVC {

	static private $instance = null;
	private $startTime;
	private $resources = array();
	private $viewsPathResolver = null;
	private $controllersPathResolver = null;

	private function __construct() {
		$this->startTime = microtime(true);

		// initialize default views path resolver
		if(defined('TINYMVC_PROJECT_VIEWS_PATH')) {
			$this->setViewsPathResolver(new TinyMVCPathResolver(TINYMVC_PROJECT_VIEWS_PATH . '/$1'));
		}
		else {
			throw new TinyMVCException("Undefined TINYMVC_PROJECT_VIEWS_PATH");
		}

		if(defined('TINYMVC_PROJECT_CONTROLLERS_PATH')) {
			$this->setControllersPathResolver(new TinyMVCPathResolver(TINYMVC_PROJECT_CONTROLLERS_PATH . '/$1ActionController.class.php'));
			//$actionControllerClassFile = TINYMVC_PROJECT_CONTROLLERS_PATH . '/' . ucfirst($moduleName) . 'ActionController.class.php';
		}
		else {
			throw new TinyMVCException("Undefined TINYMVC_PROJECT_CONTROLLERS_PATH");
		}

	}

	private function __clone() {
	}

	/**
	 * get class instance
	 * @return TinyMVC
	 */
	static public function getInstance() {
 	if(self::$instance == null) {
			try {
				if(!defined('TINYMVC_PATH')) {
					throw new TinyMVCException('TINYMVC_PATH has not been definded');
				}
				else	{
					if(file_exists(TINYMVC_PATH)) {
						self::$instance = new TinyMVC();
					}
					else {
						throw new TinyMVCException('Incorrect TINYMVC_PATH: ' . TINYMVC_PATH);
					}
				}

			}
			catch(Exception $exception) {
				$exception->handleException();
			}
		}
		return self::$instance;
	}

	/**
	 * get views path resolver
	 * @return TinyMVCPathResolver views path resolver
	 */
	public function getViewsPathResolver() {
		return $this->viewsPathResolver;
	}

	/**
	 * set views path resolver
	 * @param TinyMVCPathResolver $viewsPathResolver views path resolver
	 */
	public function setViewsPathResolver(TinyMVCPathResolver $pathResolver) {
		$this->viewsPathResolver = $pathResolver;

		if(!file_exists($this->viewsPathResolver->resolve('.'))) {
			throw new TinyMVCException("Incorrect views folder: " . $this->viewsPathResolver->resolve('.'));
		}
	}

	/**
	 * get controllers path resolver
	 * @return TinyMVCPathResolver controllers path resolver
	 */
	public function getControllersPathResolver() {
		return $this->controllersPathResolver;
	}

	/**
	 * set controllers path resolver
	 * @param TinyMVCPathResolver $viewsPathResolver controllers path resolver
	 */
	public function setControllersPathResolver(TinyMVCPathResolver $pathResolver) {
		$this->controllersPathResolver = $pathResolver;
	}

	/**
	 * add new path to PHP include_path
	 * @param string $path path to add
	 */
	public function addIncludePath($path) {
	 try {
			if(file_exists($path)) {
			 $includePath = ini_get('include_path');
			 $includePath.= PATH_SEPARATOR . $path;

			 ini_set('include_path', $includePath);
			}
			else {
				throw new TinyMVCException("Invalid include path: $path");
			}
	 }
	 catch(Exception $exception) {
			$exception->handleException();
	 }
	}

	/**
	 * add new resource to Framework
	 * @param TinyMVCResource $resource
	 */
	public function addResource(TinyMVCResource $resource) {
		$this->resources[$resource->getName()] = $resource;
	}

	/**
	 * get execution time since TinyMVC object was created until now
	 * @return float execution time
	 */
	public function getExecTime() {
		return microtime(true) - $this->startTime;
	}

	/**
	 * get Resource object by name
	 * @param string $resourceName
	 * @return TinyMVCResource resource object
	 */
	public function getResource($resourceName) {
		if(isset($this->resources[$resourceName])) {
			return $this->resources[$resourceName];
		}
		else {
			throw new TinyMVCException("Unknown resource: $resourceName");
		}
	}

	/**
	 * loading addon by name
	 * @param string $addonName addon name
	 * @param string $initFile initialization script
	 */
	public function loadAddon($addonName, $initFile = 'init.php') {
		$initFilePath = TINYMVC_ADDONS_PATH . '/' . $addonName . '/' . $initFile;
		if(file_exists($initFilePath)) {
			include_once($initFilePath);
		}
		else {
			throw new TinyMVCException("Unable to load addon: $addonName (file: $initFilePath does not exists!)");
		}
	}

}
